package com.rmfyzxfw.caseprocess.manager.redisson;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;


/**
 * Redisson工具类
 * @author Gyy
 * @date 2022-09-20
 */
@Slf4j
@Component
public class RedissonManager {

    @Resource
    private RedissonClient redissonClient;


    /**缓存*/
    public void set(String key,Object value,long expired){
        set(key, value, expired, TimeUnit.SECONDS);
    }

    /**缓存*/
    public void set(String key, Object value, long expired, TimeUnit timeUnit){
        RBucket<Object> bucket = redissonClient.getBucket(key);
        bucket.set(value,expired, timeUnit);
    }


    /**缓存*/
    public void set(String key,Object value){
        RBucket<Object> bucket = redissonClient.getBucket(key);
        bucket.set(value);
    }

    /**缓存*/
    public void setAndKeepTTL(String key,Object value){
        RBucket<Object> bucket = redissonClient.getBucket(key);
        bucket.setAndKeepTTL(value);
    }

    /**获取缓存*/
    public Object get(String key){
        RBucket<Object> bucket = redissonClient.getBucket(key);
        return bucket.get();
    }


    /**获取Integer*/
    public Integer getInteger(String key) {
        return Convert.toInt(get(key));
    }

    /**获取Integer*/
    public Long getLong(String key) {
        return Convert.toLong(get(key));
    }

    /**获取字符串*/
    public String getString(String key){
        return Convert.toStr(get(key));
    }

    /**删除缓存*/
    public boolean delete(String key){
        return redissonClient.getBucket(key).delete();
    }

    /**判断保存到缓存内容是否过期*/
    public boolean isExit(String key){
        return redissonClient.getBucket(key).isExists();
    }

    /**获取map对象*/
    public <K,V> RMap<K,V> getMap(String objectName){
        RMap<K,V> map = redissonClient.getMap(objectName);
        return map;
    }

    /**获取有序集合*/
    public <V> RSortedSet<V> getRSortedSet(String objectName){
        RSortedSet<V> sortedSet = redissonClient.getSortedSet(objectName);
        return sortedSet;
    }

    /**获取集合*/
    public <V> RSet<V> getRSet(String objectName){
        RSet<V> set = redissonClient.getSet(objectName);
        return set;
    }

    /**获取列表*/
    public <V> RList<V> getRList(String objectName){
        RList<V> rList = redissonClient.getList(objectName);
        return rList;
    }

    /**获取队列*/
    public <V> RQueue<V> getRQueue(String objectName){
        RQueue<V> rQueue = redissonClient.getQueue(objectName);
        return rQueue;
    }

    /**获取双端队列*/
    public <V> RDeque<V> getRDeque(String objectName){
        RDeque<V> rDeque = redissonClient.getDeque(objectName);
        return rDeque;
    }

    /**获取锁*/
    public RLock getRLock(String objectName){
        RLock rLock = redissonClient.getLock(objectName);
        return rLock;
    }

    /**获取读取锁*/
    public RReadWriteLock getRWLock(String objectName){
        RReadWriteLock lock = redissonClient.getReadWriteLock(objectName);
        return lock;
    }

    /**获取原子数*/
    public RAtomicLong getRAtomicLong(String objectName){
        RAtomicLong rAtomicLong = redissonClient.getAtomicLong(objectName);
        return rAtomicLong;
    }

    /**获取计数锁*/
    public RCountDownLatch getRCountDownLatch(String objectName){
        RCountDownLatch rCountDownLatch = redissonClient.getCountDownLatch(objectName);
        return rCountDownLatch;
    }

    /**获取消息的Topic*/
    public RTopic getRTopic(String objectName){
        return redissonClient.getTopic(objectName);
    }



    /**
     * 加锁
     *
     * @param lockKey
     */
    public void lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
    }

    /**
     * 带过期时间的锁
     *
     * @param lockKey   key
     * @param leaseTime 上锁后自动释放锁时间
     */
    public void lock(String lockKey, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(leaseTime, TimeUnit.SECONDS);
    }

    /**
     * 带超时时间的锁
     *
     * @param lockKey   key
     * @param leaseTime 上锁后自动释放锁时间
     * @param unit      时间单位
     */
    public void lock(String lockKey, long leaseTime, TimeUnit unit) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(leaseTime, unit);
    }

    /**
     * 尝试获取锁
     *
     * @param lockKey key
     * @return
     */
    public boolean tryLock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        return lock.tryLock();
    }

    /**
     * 尝试获取锁
     *
     * @param lockKey   key
     * @param waitTime  最多等待时间
     * @param leaseTime 上锁后自动释放锁时间
     * @return boolean
     */
    public boolean tryLock(String lockKey, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("RedissonManagers - tryLock异常", e);
        }

        return false;
    }

    /**
     * 尝试获取锁
     *
     * @param lockKey   key
     * @param waitTime  最多等待时间
     * @param leaseTime 上锁后自动释放锁时间
     * @param unit      时间单位
     * @return boolean
     */
    public boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            log.error("RedissonManagers - tryLock异常", e);
        }

        return false;
    }

    /**
     * 释放锁
     *
     * @param lockKey key
     */
    public void unlock(String lockKey) {
        try {
            RLock lock = redissonClient.getLock(lockKey);
            if(lock.isLocked()){
                lock.unlock();
            }
        }catch (Exception e){
            log.error("释放锁异常：{}", e);
        }
    }

    /**
     * 是否存在锁
     *
     * @param lockKey key
     * @return
     */
    public boolean isLocked(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        return lock.isLocked();
    }



    /**
     * 获取延迟队列
     *
     * @param queueCode 队列键
     * @return 队列值
     */
    public RBlockingDeque getBlockingDeque(String queueCode) {
        log.info("获取延迟队列:queueCode={}", queueCode);
        RBlockingDeque blockingDeque = redissonClient.getBlockingDeque(queueCode);
        return blockingDeque;
    }

    /**
     * 添加延迟队列
     *
     * @param message   消息
     * @param delay     时长
     * @param timeUnit  单位
     * @param queueCode 队列键
     */
    public <T> void addDelayQueue(T message, long delay, TimeUnit timeUnit, String queueCode) {
        try {
            RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque(queueCode);
            RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
            delayedQueue.offer(message, delay, timeUnit);
            log.info("添加延时队列成功，队列键：{}，队列值：{}，延迟时间：{}", queueCode, message, timeUnit.toSeconds(delay) + "秒");
        } catch (Exception e) {
            log.error("添加延时队列失败：{}", e.getMessage());
            throw new RuntimeException("添加延时队列失败");
        }
    }

    /**
     * 获取延迟队列
     *
     * @param queueCode 队列键
     * @return 队列值
     */
    public <T> T getDelayQueue(String queueCode) throws InterruptedException {
        log.info("获取延迟队列:queueCode={}",queueCode);
        RBlockingDeque blockingDeque = redissonClient.getBlockingDeque(queueCode);
        T value = (T) blockingDeque.take();
        log.info("获取延迟队列成功，返回值={}", JSON.toJSONString(value));
        return value;
    }
}
